#include <stdio.h>
#include <locale.h>

/* 设置语言环境 */
/*char *setlocal(int category， const char * locale);*/

#if 0
setlocale()函数用于设置或查询程序的当前语言环境。

如果locale不为NULL，则根据参数修改程序的当前语言环境。参数类别确定应修改程序当前语言环境的哪些部分。
	
Category			Governs
LC_ALL				All of the locale
LC_ADDRESS			Formatting of addresses and geography-related items (*)
LC_COLLATE			String collation
LC_CTYPE			Character classification
LC_IDENTIFICATION	Metadata describing the locale (*)
LC_MEASUREMENT		Settings related to measurements (metric versus US customary) (*)
LC_MESSAGES			Localizable natural-language messages
LC_MONETARY			Formatting of monetary values
LC_NAME				Formatting of salutations for persons (*)
LC_NUMERIC			Formatting of nonmonetary numeric values
LC_PAPER			Settings related to the standard paper size (*)
LC_TELEPHONE		Formats to be used with telephone services (*)
LC_TIME				Formatting of date and time values

/usr/include/x86_64-linux-gnu/bits/locale.h
#define __LC_CTYPE               0
#define __LC_NUMERIC             1
#define __LC_TIME                2
#define __LC_COLLATE             3
#define __LC_MONETARY            4
#define __LC_MESSAGES            5
#define __LC_ALL                 6
#define __LC_PAPER               7
#define __LC_NAME                8
#define __LC_ADDRESS             9
#define __LC_TELEPHONE          10
#define __LC_MEASUREMENT        11
#define __LC_IDENTIFICATION     12

成功调用setlocale()会返回一个与语言环境集相对应的不透明字符串。该字符串可以在静态存储器中分配。
返回的字符串使得使用该字符串及其关联的类别进行的后续调用将恢复该进程的语言环境的该部分。
如果无法兑现请求，则返回值为NULL。

LC_*优先级比LANG高，而LC_ALL实际就是一次设置全部的LC_*而已。但是一旦设置了 LC_ALL 就不能设置 LC_* 了，所以一般不用。
一般我们使用 LANG 来设置全部的 LC_* ，而独立设置一个LC_*为想要的设置。

比如设置 LANG=en_US.UTF-8 ，设置 LC_TIME=zh_GN.UTF-8 ， 目的在于输出时间以中文形式输出。

2023年 07月 03日 星期一 10:55:31 CST	/* LC_TIME=zh_CN.UTF-8 */
Mon 03 Jul 2023 10:55:56 AM CST			/* LC_TIME="en_US.UTF-8" */

#endif


int main()
{
	char *p = (char *)"\0";
	setlocale(__LC_ALL, p);

	printf("%s\n", setlocale(__LC_ALL, p));	/* en_US.UTF-8 */

	setlocale (LC_CTYPE, "zh_CN.UTF-8"); 
	setlocale (LC_MESSAGES, "zh_CN.UTF-8"); 

    /* LC_ALL=C 是为了去除所有本地化的设置,让命令能正确执行。 
     * 在Linux中通过locale来设置程序运行的不同语言环境,locale由ANSI C提供支持。
     */
    char *set_locale = setlocale(1, "C");
    printf("%s\n", set_locale);

	return 0;
}


#if 0

我的两个系统，用 locale 显示如下：

系统一:				/* 显示中文 */
LANG=zh_CN.utf8
LANGUAGE=
LC_CTYPE="zh_CN.utf8"
LC_NUMERIC=zh_CN.UTF-8
LC_TIME=zh_CN.UTF-8
LC_COLLATE="zh_CN.utf8"
LC_MONETARY=zh_CN.UTF-8
LC_MESSAGES="zh_CN.utf8"
LC_PAPER=zh_CN.UTF-8
LC_NAME=zh_CN.UTF-8
LC_ADDRESS=zh_CN.UTF-8
LC_TELEPHONE=zh_CN.UTF-8
LC_MEASUREMENT=zh_CN.UTF-8
LC_IDENTIFICATION=zh_CN.UTF-8
LC_ALL=

系统二:				/* 显示英文 */
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

locale是根据计算机用户所使用的语言，所在国家或者地区，以及当地的文化传统所定义的一个软件运行时的语言环境。

locale把按照所涉及到的文化传统的各个方面分成12个大类，这12个大类分别是：

1、语言符号及其分类(LC_CTYPE)
2、数字(LC_NUMERIC)
3、比较和排序习惯(LC_COLLATE)
4、时间显示格式(LC_TIME)
5、货币单位(LC_MONETARY)
6、信息主要是提示信息,错误信息,状态信息,标题,标签,按钮和菜单等(LC_MESSAGES)
7、姓名书写方式(LC_NAME)
8、地址书写方式(LC_ADDRESS)
9、电话号码书写方式(LC_TELEPHONE)
10、度量衡表达方式 (LC_MEASUREMENT)
11、默认纸张尺寸大小(LC_PAPER)
12、对locale自身包含信息的概述(LC_IDENTIFICATION)。

locale就是某一个地域内的人们的语言习惯和文化传统和生活习惯。一个地区的locale就是根据这几大类的习惯定义的，这些locale定 义文件放在/usr/share/locales目录下面。locale的定义文件都是用文本格式书写的，可以打开看里边的内容，给出了有限的注释以外，大部分东西可能都看不懂，因为是用的Unicode的字符索引方式。

比如可以看到两个德国的locale：/usr/share/locales/de 和 /usr/share/i18n/locales/de_DE。打开这两个locale定义，知道它们的差别在于 de使用的是欧洲的排序、比较和缩进习惯，而de_DE用的是德国的标准习惯。

例如 zh_CN.GB2312 到底是在说什么？ 
Locale是软件在运行时的语言环境, 它包括语言(Language), 地域 (Territory) 和字符集(Codeset)。一个locale的书写格式为: 语言[_地域[.字符集]]。所以说呢，locale总是和一定的字符集相联系的。

与中文输入关系最密切的就是LC_CTYPE，LC_CTYPE规定了系统内有效的字符以及这些字符的分类， 诸如什么是大写字母，小写字母，大小写转换，标点符号、可打印字符和其他的字符属性等方面。而locale定义zh_CN中最最重要的一项就是定义了汉字(Class“hanzi”)这一个大类，当然也是用Unicode描述的，这就让中文字符在Linux系统中成为合法的有效字符，而且不论它们是用什么字符集编码的。

怎样设定locale呢？

设定locale就是设定12大类的locale分类属性，即12个LC_。除了这12个变量可以设定以外，为了简便起见，还有两个变量：LC_ALL和LANG。它们之间有一个优先级的关系：LC_ALL > LC_ >LANG。可以这么说，LC_ALL是最上级设定或者强制设定，而LANG是默认设定值。

locale是这样设定的：

1、如果你需要一个纯中文的系统的话，设定LC_ALL= zh_CN.XXXX，或者LANG=zh_CN.XXXX都可以，当然你可以两个都设定，但正如上面所讲，LC_ALL的值将覆盖所有其他的locale设定，不要作无用功。

2、如果你只想要一个可以输入中文的环境，而保持菜单、标题，系统信息等等为英文界面，那么只需要设定 LC_CTYPE＝zh_CN.XXXX，LANG=en_US.XXXX就可以了。这样LC_CTYPE＝zh_CN.XXXX，而LC_COLLATE＝LC_MESSAGES＝……＝ LC_PAPER＝LANG＝en_US.XXXX。

#endif